import React, { ChangeEventHandler, useEffect, useState } from "react"
import { Button, message, Modal, Input, Table, Dropdown, Space } from "antd"
import type { MenuProps } from 'antd';
import { EditOutlined, EyeOutlined, MenuFoldOutlined, UploadOutlined, CameraOutlined, DownloadOutlined } from '@ant-design/icons';
import JSZip from 'jszip'
import { getStorageManager } from '@/file_storage'
import { dataURItoBlob, sanitizeFileName, uniqueName, downloadByBlob, ensureExtName } from '@/common/utils'
import log from "@/common/log"
import LazyImage from "@/components/LazyImage"
import { useSelector, useDispatch } from "react-redux";
import { State } from "@/reducers";
import { listVisions } from "@/actions";
import { askBg } from "@/ext/ipc";
import './index.less'

export type Vision = {
    name: string;
    fullPath: string;
    createTime: Date;
}

export default function VisualList() {

    const dispatch = useDispatch()
    const visions = useSelector((state: State) => state.visions)
    const [isEditing, setIsEditing] = useState<boolean>(false)
    const [searchImageText, setSearchImageText] = useState<string | undefined>()

    // 上传Visual
    const onImageFileChange: ChangeEventHandler<HTMLInputElement> = (e) => {
        const files = [].slice.call(e.target.files)
        if (!files || !files.length) return

        const read = (file: File) => {
            return new Promise((resolve, reject) => {
                const reader = new FileReader()

                reader.onload = (readerEvent) => {
                    try {
                        const dataUrl = readerEvent.target!.result
                        const obj = storeImage({ dataUrl, name: file.name })
                        resolve(obj)
                    } catch (e) {
                        resolve({ err: e, fileName: file.name })
                    }
                }

                reader.readAsDataURL(file)
            })
        }

        const storeImage = ({ dataUrl, name }: { dataUrl: any, name: string }) => {
            return uniqueName(name, {
                check: (name: string) => {
                    return getStorageManager()
                        .getVisionStorage()
                        .exists(name)
                        .then(result => !result)
                }
            })
                .then((fileName: string) => {
                    return getStorageManager()
                        .getVisionStorage()
                        .write(sanitizeFileName(fileName), dataURItoBlob(dataUrl))
                        .then(() => fileName)
                })
                .catch((e: Error) => {
                    log.error(e.stack)
                })
        }

        Promise.all(files.map(read))
            .then(fileNames => {
                message.success(`${fileNames.length} image files imported into Vision tab`)
                dispatch(listVisions() as any)
            })
            .catch(e => {
                log.error(e.stack)
            })
    }
    // 导出全部
    const exportAllVisions = () => {
        const zip = new JSZip()
        const visionStorage = getStorageManager().getVisionStorage()

        visionStorage.list().then((visions: any) => {

            if (visions.length === 0) {
                message.error('No vision to export')
                return
            }

            const ps = visions.map((ss: any) => {
                return visionStorage.read(ss.fullPath, 'ArrayBuffer')
                    .then((buffer: any) => {
                        zip.file(ss.name, buffer, { binary: true })
                    })
            })

            return Promise.all(ps)
                .then(() => {
                    zip.generateAsync({ type: 'blob' })
                        .then(function (blob: any) {
                            downloadByBlob(blob, 'vision-images-export.zip')
                        })
                })
        })
    }
    // 复制
    const duplicateVision = async (name: string) => {
        const imageName = name;
        const visionStorage = getStorageManager().getVisionStorage()
        const path = visionStorage.getPathLib()
        const dirPath = path.dirname(imageName)
        const getNewPath = (newName: string) => path.join(dirPath, newName)
        const getNewName = async () => {
            return await uniqueName(imageName, {
                generate: (old: string, step = 1) => {
                    const reg = /-(\d+)$/
                    const m = old.match(reg)

                    if (!m) return `${old}-${step}`
                    return old.replace(reg, (_, n) => `-${parseInt(n, 10) + step}`)
                },
                check: (fileName: string) => {
                    return visionStorage.fileExists(getNewPath(fileName)).then(exists => {
                        return !exists
                    })
                }
            })
        }

        const newImageName = await getNewName();
        let finalImageName = newImageName;
        Modal.confirm({
            title: '复制',
            content: <Input defaultValue={newImageName} onChange={e => {
                finalImageName = e.target.value
            }} />,
            onOk: async () => {
                const fullPath = visionStorage.filePath(getNewPath(sanitizeFileName(finalImageName)))
                const exists = await visionStorage.fileExists(fullPath)
                if (exists) {
                    const msg = `'${finalImageName}' already exists`
                    message.error(msg)
                    throw new Error(msg)
                }
                return visionStorage.copy(imageName, fullPath, false, false)
                    .then(
                        () => {
                            message.success(`Successfully duplicated as '${finalImageName}'`)
                            dispatch(listVisions() as any)
                            return true
                        },
                        (e: Error) => {
                            log.error(e)
                            const msg = 'Failed to duplicate vision image: ' + e.message
                            message.error(msg)
                            throw new Error(msg)
                        }
                    )
            }
        })
    }
    // 删除
    const deleteVision = (name: string) => {
        return Modal.confirm({
            title: '确定删除？',
            okText: '删除',
            cancelText: '取消',
            onOk: async () => {
                return await getStorageManager()
                    .getVisionStorage()
                    .remove(name)
                    .then(() => {
                        message.success('Successfully deleted')
                        dispatch(listVisions() as any)
                    })
                    .catch(e => {
                        console.error(e)
                    })
            },
            onCancel: () => {
                return Promise.resolve(true)
            }
        })
    }
    // 重命名
    const renameVision = (oldName: string, newName: string) => {
        return getStorageManager()
            .getVisionStorage()
            .rename(oldName, ensureExtName('.png', newName))
            .then(() => {
                message.success('Successfully renamed')
                dispatch(listVisions() as any)
            })
            .catch(e => {
                message.error(e.message)
                throw e
            })
    }
    // 导出图片
    const exportVision = async (fullPath: string, name: string) => {
        const buffer: any = await getStorageManager().getVisionStorage().read(fullPath, 'ArrayBuffer');
        const blob = new Blob([new Uint8Array(buffer)]); // 转blob
        downloadByBlob(blob, name);
    }
    //  <Button onClick={() => exportVision(item.fullPath, item.name)}>下载</Button>

    const onClickActionMenu = (key: string, vision: Vision) => {
        switch (key) {
            case 'duplicate':
                return duplicateVision(vision.name)

            case 'name_to_target':
                return  // copyNameToTarget(vision.name)

            case 'delete':
                return deleteVision(vision.name)
        }
    }

    const actionMenuItems: MenuProps['items'] = [
        {
            label: '复制',
            key: 'duplicate'
        },
        {
            label: '添加到目标框',
            key: 'name_to_target'
        },
        { type: 'divider' },
        {
            label: '删除',
            key: 'delete'
        }
    ];

    const columns = [
        {
            title: 'Image',
            dataIndex: 'fullPath',
            key: 'fullPath',
            width: 116,
            render: (fullPath: string, vision: Vision) => {
                return (
                    <LazyImage fullName={vision.name} storageType="vision" />
                )
            }
        },
        {
            title: 'Name',
            dataIndex: 'name',
            key: 'name',
            render: (name: string, vision: Vision) => {
                return (
                    <div className="vision-name-1" id={name}>
                        {
                            isEditing ? <Input defaultValue={vision.name}
                                onBlur={(e) => {
                                    const finalName = e.target.value;
                                    renameVision(vision.name, finalName)
                                    setIsEditing(false)
                                }}
                            /> : <span>{vision.name}
                                <EditOutlined
                                    style={{ marginLeft: '10px', cursor: 'pointer' }}
                                    onClick={() => {
                                        setIsEditing(true)
                                    }}
                                />
                            </span>
                        }
                    </div>
                )
            }
        },
        {
            title: 'Action',
            key: 'ops',
            width: 100,
            render: (text: string, vision: Vision, index: number) => {
                return (
                    <div className="vision-actions">
                        <Button
                            size="small"
                            shape="circle"
                            onClick={(ev) => {
                                // viewVision(vision.name)
                            }}
                        >
                            <EyeOutlined />
                        </Button>

                        <Dropdown
                            menu={{
                                items: actionMenuItems,
                                onClick: ({ key }) => { onClickActionMenu(key, vision) }
                            }}
                            trigger={['click']}
                        >
                            <Button
                                size="small"
                                shape="circle"
                            >
                                <MenuFoldOutlined />
                            </Button>
                        </Dropdown>
                    </div>
                )
            }
        }
    ]

    const search = (searchImageText || '').toLowerCase().trim()

    const matchedVisions = visions.filter(vision => {
        if (search.length === 0) return true
        return vision.name.toLowerCase().indexOf(search) !== -1
    })

    const tableConfig = {
        columns,
        dataSource: matchedVisions,
        pagination: false,
        bordered: true,
        size: 'middle',
        rowKey: (record: Vision) => {
            return record.fullPath + '__' + record.createTime.getTime()
        },
    } as any

    // 区域截图
    const handleTakeSelectionScreenshot = async () => {
        // 给tab发送消息，去选择区域
        askBg('PANEL_SELECT_AREA_ON_CURRENT_PAGE')
    }

    // 请求数据
    useEffect(() => {
        dispatch(listVisions() as any)
    }, [])

    return <div>
        <div className="vision-content">
            <div className="vision-top-actions">
                <div className="main-actions">
                    <div className="main-actions-left">
                        <Space>
                            <Button
                                icon={<UploadOutlined />}
                                title="上传图片"
                            >
                                <input
                                    multiple
                                    type="file"
                                    accept="image/*"
                                    id="select_image_files"
                                    onChange={onImageFileChange}
                                    style={{ display: 'none' }}
                                />
                            </Button>
                            <Button
                                onClick={handleTakeSelectionScreenshot}
                                icon={<CameraOutlined />}
                                title="截图"
                            />
                            <Button
                                onClick={exportAllVisions}
                                title='导出所有图片'
                                icon={<DownloadOutlined />}
                            />
                            <Input.Search
                                style={{ flex: 0.8 }}
                                placeholder="搜索图片"
                                onChange={e => setSearchImageText(e.target.value)}
                            />
                        </Space>
                    </div>
                </div>
            </div>
            <Table {...tableConfig} />
        </div>
    </div>
}